home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / dev / misc / XRefGED20API.lha / XRef / Tools / golded / XRefAPI.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-06  |  31.2 KB  |  1,097 lines

  1. /*
  2. ** $PROJECT: XRef-GoldEDAPI
  3. **
  4. ** $VER: xrefapi.c 1.5 (02.04.95)
  5. **
  6. ** by
  7. **
  8. ** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
  9. **
  10. ** (C) Copyright 1994
  11. ** All Rights Reserved !
  12. **
  13. ** $HISTORY:
  14. **
  15. ** 02.04.95 : 001.005 : changed to GoldED2.0 API client style
  16. ** 16.09.94 : 001.004 : some internal improvements
  17. ** 13.09.94 : 001.003 : select window added
  18. ** 12.09.94 : 001.002 : rexx command implemented
  19. ** 11.09.94 : 001.001 : initial
  20. */
  21.  
  22. /* --------------------------- version defines ---------------------------- */
  23.  
  24. /*FS*/ /* $STARTDEFINE: "BumpRev defines"*/
  25. #define VERSION  1
  26. #define REVISION 5
  27. #define DATE "2.4.95"
  28. #define VERS "XRefAPI 1.5"
  29. #define VSTRING "XRefAPI 1.5 (2.4.95)\r\n"
  30. #define VERSTAG "\0$VER: XRefAPI 1.5 (2.4.95)"
  31. /*FE*/ /* $ENDDEFINE:   */
  32.  
  33. /* ------------------------------- include -------------------------------- */
  34.  
  35. #include "/source/Def.h"
  36.  
  37. #include <rexx/errors.h>
  38.  
  39. #include "/lib/xrefsupport.h"
  40.  
  41. #include "golded:api/include/golded.h"
  42.  
  43. /* ------------------------------- AutoDoc -------------------------------- */
  44.  
  45. /*FS*/ /*"AutoDoc"*/
  46. /*GB*** XRef-Tools/XRefAPI ***************************************************
  47.  
  48. $VER: XRefAPI.doc
  49.  
  50. NAME
  51.     XRefAPI - GoldED API client for use with the xref.library to complete
  52.               phrases
  53.  
  54. FUNCTION
  55.     Just run GoldED and load this as an API-Client ! Then you have the
  56.     following new ARexx command :
  57.  
  58. TEMPLATE
  59.     XREFPHRASE CATEGORY/K,TYPES/K,MATCH/K,COMPLETEBEGIN/S,UPPERCASE/S,
  60.                SPACE/S
  61.  
  62. FORMAT
  63.     XREFPHRASE [CATEGORY <string|pattern>] [TYPES <to search for>]
  64.                [MATCH matchmode] [COMPLETEBEGIN] [UPPERCASE] [SPACE]
  65.  
  66.  
  67.  
  68. FUNCTION
  69.     the XREFPHRASE command tries to complete the current pharse (before 
  70.     the cursor) with the entries from the xref.library. This is done by
  71.     two algorithms :
  72.         - First uppercase letter match :
  73.             This means each character in the phrase must match the
  74.             next uppercase letter in the name ! For example :
  75.             the pharse "ow" matches "OpenWindow()" ("O"pen"W"indow())
  76.         - Second begin match :
  77.             The entry must match the beginning of the phrase !
  78.     There is a automatic two switch between to algorithms :
  79.         - if the pharse consists only of lower case letters the
  80.           uppercase letter match algorithm is used !
  81.         - if in the pharse is a uppercase letter the begin match
  82.           algorithm is used !
  83.     Note the matchmode RECURSIVE uses only the begin match algorithm !
  84.  
  85. INPUTS
  86.     CATEGORY (STRING) - category string|pattern to search in
  87.  
  88.     TYPES (STRING) - types, which would only match ("function","struct",
  89.         "function|struct" or so on)
  90.  
  91.     MATCH (STRING) - one of the following three matchmode strings 
  92.         (default is FIRST) :
  93.         FIRST - always get the first entry, which match the given pharse
  94.         RECURSIVE - much like a Tab-Completion algorithm, it search for
  95.             all entries matches the given phrase and complete it to the
  96.             last character equal to all entries ! If you pass UPPERCASE
  97.             argument the search is case-insenitive !
  98.             If you pass the phrase you passed last and cannot be more
  99.             completed, it switches to the SELECT matchmode and displays
  100.             the window !
  101.             This mode uses everytime the begin match algorithm !!!
  102.         SELECT - it searchs for all entries matching the given phrase and
  103.             if more than one is found, it opens a window you can select
  104.             one !
  105.  
  106.     COMPLETEBEGIN (BOOLEAN) - use the begin match algorithm instead of
  107.         uppercase letter match !
  108.  
  109.     UPPERCASE (BOOLEAN) - convert the phrase to upper
  110.  
  111.     SPACE (BOOLEAN) - if a name is found and inserted place a space behind
  112.  
  113. RESULTS
  114.     the command returns RC_OK, if it could complete the pharse. RC_WARN
  115.     if not !
  116.  
  117. EXAMPLE
  118.     'XREFPHRASE CATEGORY #?AutoDoc TYPES "function"' :
  119.  
  120.     This command will parse all AutoDoc categories and compare the given
  121.     shortcut with any function found in the xreffiles.For example the two
  122.     letters "ow" will completed to "OpenWindow(", if you have the
  123.     sys_autodoc.xref installed from the XRef-System package !
  124.  
  125. SEE ALSO
  126.     XRef-System.guide, GoldED/API, xref.library/ParseXRef(), ParseXRef
  127.  
  128. *****************************************************************************/
  129. /*FE*/
  130.  
  131. /* ------------------------------- defines -------------------------------- */
  132.  
  133. /*FS*/ /*"Defines"*/
  134. #define BUFFER_LEN         512
  135.  
  136. enum {
  137.    COMPLETE_UPPERCASELETTER,     /* complete phrase using characters as upper
  138.                                   * case letters only in the string
  139.                                   */
  140.    COMPLETE_BEGIN,               /* comlete phrase using given WORD as the
  141.                                   * beginning of the WORD
  142.                                   */
  143.    COMPLETE_BEGIN_NOCASE,        /* same as COMPLETE_BEGIN, but case-insensitive
  144.                                   */
  145.    COMPLETE_RECURSIVE,           /* tab-completion like algrorithm */
  146.    COMPLETE_RECURSIVE_NOCASE,    /* same as COMPLETE_RECURSIVE, case-insensitive */
  147.  
  148.    };
  149.  
  150.  
  151. enum {
  152.    MATCH_FIRST,
  153.    MATCH_RECURSIVE,
  154.    MATCH_SELECT,
  155.    };
  156.  
  157. #define XREFPHRASE_ARGS          "CATEGORY/K,TYPES/K,MATCH/K,COMPLETEBEGIN/S,UPPERCASE/S,SPACE/S"
  158.  
  159. #define MAX_PARAMETER            6
  160.  
  161. #define EOS                      '\0'
  162.  
  163. #define USETAG(tag,check)        ((check) ? (tag) : TAG_IGNORE)
  164.  
  165. #define PUDDLE_SIZE              512
  166.  
  167. #define XDISTANCE                8
  168. #define YDISTANCE                4
  169.  
  170. /*FE*/
  171.  
  172. /* ----------------------------- structures ------------------------------- */
  173.  
  174. /*FS*/ /*"Structures"*/
  175. struct RexxCommands
  176. {
  177.    STRPTR rxc_Command;
  178.    LONG (*rxc_Handler) (struct GlobalData *,struct APIMessage *);
  179.    STRPTR rxc_Template;
  180. };
  181.  
  182. struct GlobalData
  183. {
  184.    struct MsgPort *gd_ApiPort;
  185.    struct MsgPort *gd_RexxPort;
  186.  
  187.    STRPTR gd_GoldEDHost;
  188.  
  189.    ULONG gd_Result;
  190.    ULONG gd_Mode;
  191.    ULONG gd_Match;
  192.    LONG gd_Found;
  193.  
  194.    APTR gd_FoundPool;
  195.    struct List gd_FoundList;
  196.  
  197.    struct Hook gd_Hook;
  198.  
  199.    ULONG gd_Para[MAX_PARAMETER];
  200.  
  201.    UBYTE gd_Buffer[BUFFER_LEN];
  202.    UBYTE gd_Name[BUFFER_LEN];
  203.    UBYTE gd_LastName[BUFFER_LEN];
  204.  
  205.    struct Library *gd_XRefBase;
  206.    struct APIModifyRequest gd_Modify;
  207. };
  208.  
  209. #define XRefBase     gd->gd_XRefBase
  210. /*FE*/
  211.  
  212. /* ------------------------------ prototypes ------------------------------ */
  213.  
  214. /*FS*/ /*"Prototypes"*/
  215. RegCall GetA4 ULONG hook(REGA0 struct Hook *hook,REGA2 struct XRefFileNode *xref,REGA1 struct xrmXRef *msg);
  216.  
  217. void search_command(struct GlobalData *gd,struct APIMessage *msg);
  218.  
  219. LONG RexxCmd_XRefPhrase(struct GlobalData *gd,struct APIMessage *msg);
  220.  
  221. BOOL alloc_name(struct GlobalData *gd,STRPTR name);
  222.  
  223. BOOL send_rexxcommand(struct GlobalData *gd,STRPTR cmd);
  224.  
  225. struct Node *select_node(struct List *list,struct Screen *screen);
  226.  
  227. void parse_typestring(STRPTR typestr,ULONG *typearray);
  228.  
  229.  
  230. /*FE*/
  231.  
  232. /* -------------------------- static data items --------------------------- */
  233.  
  234. /*FS*/ /*"Contants"*/
  235. static const STRPTR version = VERSTAG;
  236. static const STRPTR prgname = "XRefAPI";
  237.  
  238. static struct RexxCommands rexxcmd[] = {
  239.    {"XREFPHRASE",RexxCmd_XRefPhrase,XREFPHRASE_ARGS},
  240.    {NULL}};
  241.  
  242. static const STRPTR xreftype_names[XREFT_MAXTYPES] = {
  243.    "generic",
  244.    "function",
  245.    "command",
  246.    "include",
  247.    "macro",
  248.    "struct",
  249.    "field",
  250.    "typedef",
  251.    "define"};
  252.  
  253. static struct TagItem xrefapitags[] = {
  254.    {API_Client_Name       ,(ULONG) "XRefAPI"},
  255.    {API_Client_Copyright  ,(ULONG) "©1994 Stefan Ruppert"},
  256.    {API_Client_Purpose    ,(ULONG) VERS "\n\nPhrase completion with xref.library"},
  257.    {API_Client_Template   ,(ULONG) "XREFPHRASE " XREFPHRASE_ARGS},
  258.    {TAG_DONE,}};
  259.  
  260. static STRPTR matchmodes[] = {
  261.    "FIRST",
  262.    "RECURSIVE",
  263.    "SELECT",
  264.    NULL};
  265. /*FE*/
  266.  
  267.  
  268. /* ------------------------- template definition -------------------------- */
  269.  
  270. /*FS*/ /*"Program Template"*/
  271. #define template    "HOST/K/A"
  272.  
  273. enum {
  274.    ARG_HOST,
  275.    ARG_MAX};
  276. /*FE*/
  277.  
  278. /* --------------------------- main entry point --------------------------- */
  279.  
  280. /*FS*/ /*"int main(void)"*/
  281. int main(void)
  282. {
  283.    struct RDArgs *args;
  284.    LONG para[ARG_MAX];
  285.    STRPTR obj = prgname;
  286.    LONG err = 0;
  287.  
  288.    LONG i;
  289.  
  290.    /* clear args buffer */
  291.    for(i = 0 ; i < ARG_MAX ; i++)
  292.       para[i] = 0;
  293.  
  294.    /* here set your defaults : para[ARG_#?] = default_value; */
  295.  
  296.    if(args = ReadArgs(template,para,NULL))
  297.    {
  298.       struct GlobalData *gd;     
  299.  
  300.  
  301.       DB(("golded host : %s\n",para[ARG_HOST]));
  302.       if((gd = AllocMem(sizeof(struct GlobalData),MEMF_ANY | MEMF_CLEAR)))
  303.       {
  304.          if((gd->gd_ApiPort = CreateMsgPort()))
  305.          {
  306.             if((gd->gd_RexxPort = CreateMsgPort()))
  307.             {
  308.                gd->gd_GoldEDHost   = (STRPTR)   para[ARG_HOST];
  309.                gd->gd_Hook.h_Entry = (HOOKFUNC) hook;
  310.                gd->gd_Hook.h_Data  = gd;
  311.  
  312.                sprintf(gd->gd_Buffer,"API PORT=%ld CLASS=%ld",
  313.                                      gd->gd_ApiPort,
  314.                                      API_CLASS_ROOT | API_CLASS_REXX);
  315.  
  316.                if(send_rexxcommand(gd,gd->gd_Buffer) && gd->gd_Result == RC_OK)
  317.                {
  318.                   struct APIMessage *apimsg;
  319.                   struct APIMessage *msg;
  320.  
  321.                   BOOL active = TRUE;
  322.  
  323.                   DB(("xrefapi active !\n"));
  324.  
  325.                   do
  326.                   {
  327.                      WaitPort(gd->gd_ApiPort);
  328.  
  329.                      while((apimsg = (struct APIMessage *) GetMsg(gd->gd_ApiPort)))
  330.                      {
  331.                         for(msg = apimsg ; msg ; msg = msg->api_Next)
  332.                         {
  333.                            if(msg->api_State == API_STATE_NOTIFY)
  334.                            {
  335.                               switch(msg->api_Class)
  336.                               {
  337.                               case API_CLASS_ROOT:
  338.                                  switch(msg->api_Action)
  339.                                  {
  340.                                  case API_ACTION_DIE:
  341.                                     active = FALSE;
  342.                                     break;
  343.                                  case API_ACTION_INTRODUCE:
  344.                                     msg->api_Data = xrefapitags;
  345.                                     break;
  346.                                  }
  347.                                  break;
  348.                               case API_CLASS_REXX:
  349.                                  switch(msg->api_Action)
  350.                                  {
  351.                                  case API_ACTION_COMMAND:
  352.                                     search_command(gd,msg);
  353.                                     break;
  354.                                  default:
  355.                                     msg->api_Error = API_ERROR_UNKNOWN;
  356.                                  }
  357.                                  break;
  358.                               default:
  359.                                  msg->api_Error = API_ERROR_UNKNOWN;
  360.                               }
  361.                            }
  362.                         }
  363.  
  364.                         ReplyMsg((struct Message *) apimsg);
  365.                      }
  366.                   } while(active);
  367.                   SetIoErr(0);
  368.                }   
  369.                DeleteMsgPort(gd->gd_RexxPort);
  370.             }
  371.             DeleteMsgPort(gd->gd_ApiPort);
  372.          }
  373.          FreeMem(gd,sizeof(struct GlobalData));
  374.       }
  375.       FreeArgs(args);
  376.    }
  377.  
  378.    if(!err)
  379.       err = IoErr();
  380.  
  381.    if(err)
  382.    {
  383.       PrintFault(err,obj);
  384.       return(RETURN_ERROR);
  385.    }
  386.  
  387.    return(RETURN_OK);
  388. }
  389. /*FE*/
  390.  
  391. /* ---------------------- search for a given command ---------------------- */
  392.  
  393. /*FS*/ /*"void search_command(struct GlobalData *gd,struct APIMessage *msg)"*/
  394. void search_command(struct GlobalData *gd,struct APIMessage *msg)
  395. {
  396.    struct APIRexxNotify *notify = (struct APIRexxNotify *) msg->api_Data;
  397.    struct RexxCommands  *rxcmd  = rexxcmd;
  398.    LONG len;
  399.  
  400.    notify->arn_RC = RC_WARN;
  401.  
  402.    while(rxcmd->rxc_Command)
  403.    {
  404.       len = strlen(rxcmd->rxc_Command);
  405.  
  406.       if(!strncmp(notify->arn_Command,rxcmd->rxc_Command,len))
  407.       {
  408.          struct RDArgs *rdargs;
  409.          struct RDArgs *args;
  410.          LONG i;
  411.  
  412.          msg->api_State = API_STATE_CONSUMED;
  413.  
  414.          strncpy(gd->gd_Buffer,¬ify->arn_Command[len],BUFFER_LEN);
  415.          strncat(gd->gd_Buffer,"\n",BUFFER_LEN);
  416.  
  417.          if(rdargs = (struct RDArgs *) AllocDosObject(DOS_RDARGS,NULL))
  418.          {
  419.             rdargs->RDA_Source.CS_Buffer   = gd->gd_Buffer;
  420.             rdargs->RDA_Source.CS_Length   = strlen(gd->gd_Buffer);
  421.  
  422.             for(i=0 ; i < MAX_PARAMETER ; i++)
  423.                gd->gd_Para[i]=0;
  424.  
  425.             DB(("rdargs at : %lx\n",rdargs));
  426.             
  427.             if((args = ReadArgs(rxcmd->rxc_Template,(LONG *) gd->gd_Para,rdargs)))
  428.             {
  429.                DB(("args at %lx\n",args));
  430.  
  431.                notify->arn_RC = rxcmd->rxc_Handler(gd,msg);
  432.  
  433.                FreeArgs(args);
  434.             }
  435.             FreeDosObject(DOS_RDARGS , rdargs);
  436.          }
  437.       }
  438.       rxcmd++;
  439.    }
  440.  
  441.    if(notify->arn_RC != RC_OK)
  442.    {
  443.       Fault(IoErr(),"XRefAPI",gd->gd_Buffer,BUFFER_LEN);
  444.       notify->arn_CommandError = gd->gd_Buffer;
  445.    }
  446. }
  447. /*FE*/
  448.  
  449. /* ----------------------- xrefphrase rexx command ------------------------ */
  450.  
  451. /*FS*/ /*"LONG RexxCmd_XRefPhrase(struct GlobalData *gd,struct APIMessage *msg)"*/
  452.  
  453. /* templates arguments */
  454. enum {
  455.    ARG_CATEGORY,
  456.    ARG_TYPES,
  457.    ARG_MATCH,
  458.    ARG_COMPLETEBEGIN,
  459.    ARG_UPPERCASE,
  460.    ARG_SPACE,
  461.    };
  462.  
  463. LONG RexxCmd_XRefPhrase(struct GlobalData *gd,struct APIMessage *msg)
  464. {
  465.  
  466.    struct EditConfig *config = msg->api_Config;
  467.    LONG *para = gd->gd_Para;
  468.    ULONG types[XREFT_MAXTYPES + 1];
  469.  
  470.    UWORD  column;
  471.    UWORD len;
  472.    STRPTR wrd;
  473.    STRPTR buf;
  474.    STRPTR begin;
  475.    STRPTR ptr2;
  476.    LONG retval = RC_WARN;
  477.  
  478.    column = config->Column;
  479.    buf    = config->CurrentBuffer;
  480.    wrd    = gd->gd_Buffer;
  481.  
  482.    /* terminate the types array */
  483.    types[0] = ~0;
  484.  
  485.    if(para[ARG_TYPES])
  486.       parse_typestring((STRPTR) para[ARG_TYPES],types);
  487.  
  488.    if(column && (buf[--column] > '@'))
  489.    {
  490.       STRPTR pattern = "#?";
  491.       ULONG xrefmatch = XREFMATCH_PATTERN_CASE;
  492.  
  493.       len = 1;
  494.       for(begin = buf + column; column && (*(begin - 1) > '@') ; --column, --begin)
  495.          len++;
  496.  
  497.       movmem(begin,wrd,len);
  498.       wrd[len] = 0;
  499.  
  500.       gd->gd_Mode = COMPLETE_UPPERCASELETTER;
  501.  
  502.       for(ptr2 = wrd; *ptr2 ; ptr2++)
  503.          if(isupper(*ptr2))
  504.          {
  505.             gd->gd_Mode = COMPLETE_BEGIN;
  506.             break;
  507.          }
  508.  
  509.       if(para[ARG_COMPLETEBEGIN])
  510.          gd->gd_Mode = COMPLETE_BEGIN;
  511.  
  512.       gd->gd_Match = MATCH_FIRST;
  513.       if(para[ARG_MATCH])
  514.       {
  515.          STRPTR *array = matchmodes;
  516.          ULONG i = MATCH_FIRST;
  517.  
  518.          while(*array)
  519.          {
  520.             if(!Stricmp(*array,(STRPTR) para[ARG_MATCH]))
  521.             {
  522.                gd->gd_Match = i;
  523.                break;
  524.             }
  525.             i++;
  526.             array++;
  527.          }
  528.          DB(("matchmode : %ld\n",gd->gd_Match));
  529.       }
  530.  
  531.       if(gd->gd_Match == MATCH_RECURSIVE)
  532.       {
  533.          if(!Stricmp(gd->gd_LastName,gd->gd_Buffer))
  534.          {
  535.             gd->gd_Match = MATCH_SELECT;
  536.  
  537.             if(para[ARG_UPPERCASE])
  538.                gd->gd_Mode = COMPLETE_BEGIN_NOCASE;
  539.             else
  540.                gd->gd_Mode = COMPLETE_BEGIN;
  541.          } else
  542.          {
  543.             strcpy(gd->gd_LastName,gd->gd_Buffer);
  544.  
  545.             if(para[ARG_UPPERCASE])
  546.                gd->gd_Mode = COMPLETE_RECURSIVE_NOCASE;
  547.             else
  548.                gd->gd_Mode = COMPLETE_RECURSIVE;
  549.          }
  550.       }
  551.  
  552.       if(gd->gd_Mode != COMPLETE_UPPERCASELETTER)
  553.       {
  554.          strcat(gd->gd_Buffer,"#?");
  555.          pattern = gd->gd_Buffer;
  556.  
  557.          if(para[ARG_UPPERCASE])
  558.             xrefmatch = XREFMATCH_PATTERN_NOCASE;
  559.       } else
  560.          for(ptr2 = wrd; *ptr2 ; ptr2++)
  561.             *ptr2 = toupper(*ptr2);
  562.  
  563.       DB(("word : %s\n",gd->gd_Buffer));
  564.  
  565.       /* cleanup */
  566.       NewList(&gd->gd_FoundList);
  567.       gd->gd_FoundPool = NULL;
  568.       gd->gd_Found     = 0;
  569.  
  570.       if((XRefBase = OpenLibrary("xref.library",1)))
  571.       {
  572.          if(ParseXRefTags(pattern,XREFA_XRefHook                               ,&gd->gd_Hook,
  573.                                   XREFA_Matching                               ,xrefmatch,
  574.                                   USETAG(XREFA_Category   ,para[ARG_CATEGORY]) ,para[ARG_CATEGORY],
  575.                                   USETAG(XREFA_AcceptTypes,para[ARG_TYPES])    ,types,
  576.                                   TAG_DONE))
  577.          {
  578.             if(gd->gd_Found > 1 && gd->gd_Match == MATCH_SELECT)
  579.             {
  580.                struct Screen *screen;
  581.  
  582.                if((screen = LockPubScreen(msg->api_Global->F_ScrnName)))
  583.                {
  584.                   struct Node *node;
  585.  
  586.                   if((node = select_node(&gd->gd_FoundList,screen)))
  587.                   {
  588.                      strcpy(gd->gd_Name,node->ln_Name);
  589.                      gd->gd_Found =  1;
  590.                   } else
  591.                      gd->gd_Found = -1;
  592.                   UnlockPubScreen(NULL,screen);
  593.                }
  594.             }
  595.  
  596.             if(gd->gd_FoundPool)
  597.             {
  598.                LibDeletePool(gd->gd_FoundPool);
  599.                gd->gd_FoundPool = NULL;
  600.             }
  601.  
  602.             if(gd->gd_Found == 1)
  603.             {
  604.                UWORD newlen = strlen(gd->gd_Name);
  605.  
  606.                if(gd->gd_Name[newlen - 1] == ')')
  607.                {
  608.                   gd->gd_Name[newlen - 1] = 0;
  609.                   newlen--;
  610.                }
  611.  
  612.                if(para[ARG_SPACE])
  613.                {
  614.                   strcat(gd->gd_Name," ");
  615.                   newlen++;
  616.                }
  617.  
  618.  
  619.                strncpy(gd->gd_Buffer,config->CurrentBuffer,column);
  620.                strncpy(&gd->gd_Buffer[column],gd->gd_Name,newlen);
  621.                strcpy(&gd->gd_Buffer[column + newlen],config->CurrentBuffer + config->Column);
  622.                gd->gd_Modify.mr_Next   = NULL;
  623.                gd->gd_Modify.mr_Line   = config->Line;
  624.                gd->gd_Modify.mr_Column = column + newlen;
  625.                gd->gd_Modify.mr_Data   = gd->gd_Buffer;
  626.                gd->gd_Modify.mr_Size   = column + newlen + (config->CurrentLen - config->Column);
  627.  
  628.                msg->api_Modify = &gd->gd_Modify;
  629.  
  630.                msg->api_Refresh |= API_REFRESH_LINE;
  631.  
  632.                retval = RC_OK;
  633.             } else if(gd->gd_Found == 0)
  634.                SetIoErr(ERROR_OBJECT_NOT_FOUND);
  635.             else if(gd->gd_Found == -1)
  636.                SetIoErr(ERROR_BREAK);
  637.          }
  638.          CloseLibrary(XRefBase);
  639.       }
  640.    } else
  641.       SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  642.  
  643.    return(retval);
  644. }
  645. /*FE*/
  646.  
  647. /* ------------------ callback function for ParseXRef() ------------------- */
  648.  
  649. /*FS*/ /*"ULONG hook(struct Hook *hook,struct XRefFileNode *xref,struct xrmXRef *msg)"*/
  650. RegCall GetA4 ULONG hook(REGA0 struct Hook *hook,REGA2 struct XRefFileNode *xref,REGA1 struct xrmXRef *msg)
  651. {
  652.    struct GlobalData *gd = (struct GlobalData *) hook->h_Data;
  653.  
  654.    if(msg->Msg == XRM_XREF)
  655.    {
  656.       STRPTR name = (STRPTR) GetTagData(ENTRYA_Name,NULL,msg->xref_Attrs);
  657.       STRPTR ptr;
  658.       STRPTR wrd = gd->gd_Buffer;
  659.       ULONG matched = FALSE;
  660.       ULONG num = 0;
  661.                                       
  662.       if((ptr = name))  
  663.       {
  664.          switch(gd->gd_Mode)
  665.          {
  666.          case COMPLETE_BEGIN:
  667.          case COMPLETE_BEGIN_NOCASE:
  668.             /* anything matches, because xref.library compared for us */
  669.             matched = TRUE;
  670.             break;
  671.          case COMPLETE_UPPERCASELETTER:
  672.             while(*ptr)
  673.             {
  674.                if(isupper(*ptr))
  675.                {
  676.                   if(*wrd)
  677.                   {
  678.                      if(*ptr != *wrd)
  679.                         break;
  680.                      else
  681.                         wrd++;
  682.                   }
  683.                   num++;
  684.                }
  685.                ptr++;
  686.             }
  687.             matched = (*wrd == 0 && num == strlen(gd->gd_Buffer));
  688.             break;
  689.          case COMPLETE_RECURSIVE:
  690.             /* build no memory list, just find out the maximal string, which matches */
  691.             if(gd->gd_Found == 0)
  692.                strcpy(gd->gd_Name,name);
  693.             else
  694.             {
  695.                STRPTR ptr = gd->gd_Name;
  696.  
  697.                while(*ptr && *ptr == *name)
  698.                {
  699.                   ptr++;
  700.                   name++;
  701.                }
  702.  
  703.                *ptr = EOS;
  704.  
  705.             }
  706.             gd->gd_Found = 1;
  707.             break;
  708.          case COMPLETE_RECURSIVE_NOCASE:
  709.             /* build no memory list, just find out the maximal string, which matches */
  710.             if(gd->gd_Found == 0)
  711.                strcpy(gd->gd_Name,name);
  712.             else
  713.             {
  714.                STRPTR ptr = gd->gd_Name;
  715.  
  716.                while(*ptr && toupper(*ptr) == toupper(*name))
  717.                {
  718.                   ptr++;
  719.                   name++;
  720.                }
  721.  
  722.                if(*name)
  723.                   gd->gd_Para[ARG_SPACE] = FALSE;
  724.  
  725.                *ptr = EOS;
  726.  
  727.             }
  728.             gd->gd_Found = 1;
  729.             break;
  730.          }
  731.  
  732.          if(matched)
  733.          {
  734.             DB(("found : %s\n",name));
  735.  
  736.             gd->gd_Found++;
  737.  
  738.             if(gd->gd_Match == MATCH_FIRST)
  739.             {
  740.                strcpy(gd->gd_Name,name);
  741.                return(1);
  742.             }
  743.  
  744.             if(gd->gd_Found == 1)
  745.             {
  746.                strcpy(gd->gd_Name,name);
  747.             } else
  748.             {
  749.                if(!gd->gd_FoundPool)
  750.                   gd->gd_FoundPool = LibCreatePool(MEMF_ANY | MEMF_CLEAR,PUDDLE_SIZE,PUDDLE_SIZE);
  751.  
  752.                if(!gd->gd_FoundPool)
  753.                {
  754.                   return(1);
  755.                } else
  756.                {
  757.                   if(gd->gd_Found == 2)
  758.                      alloc_name(gd,gd->gd_Name);
  759.  
  760.                   if(!alloc_name(gd,name))
  761.                      gd->gd_Found--;
  762.                }
  763.             }
  764.          }
  765.       }
  766.    }
  767.    return(0);
  768. }
  769. /*FE*/
  770.  
  771. /* ------------------------- send a Rexx command -------------------------- */
  772.  
  773. /*FS*/ /*"BOOL send_rexxcommand(struct GlobalData *gd,STRPTR cmd)"*/
  774. BOOL send_rexxcommand(struct GlobalData *gd,STRPTR cmd)
  775. {
  776.    struct MsgPort *rexxport;
  777.  
  778.    Forbid();
  779.  
  780.    if((rexxport = FindPort(gd->gd_GoldEDHost)))
  781.    {
  782.       struct RexxMsg *rxmsg;
  783.       struct RexxMsg *answer;
  784.  
  785.       if((rxmsg = CreateRexxMsg(gd->gd_RexxPort, NULL, NULL)))
  786.       {
  787.          if((rxmsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))))
  788.          {
  789.             rxmsg->rm_Action = RXCOMM | RXFF_RESULT;
  790.  
  791.             PutMsg(rexxport, &rxmsg->rm_Node);
  792.  
  793.             do
  794.             {
  795.                WaitPort(gd->gd_RexxPort);
  796.  
  797.                if((answer = (struct RexxMsg *) GetMsg(gd->gd_RexxPort)))
  798.                    gd->gd_Result = answer->rm_Result1;
  799.  
  800.             } while (!answer);
  801.  
  802.             Permit();
  803.  
  804.             if(answer->rm_Result1 == RC_OK)
  805.             {
  806.                if(answer->rm_Result2)
  807.                {
  808.                   if(gd->gd_Buffer)
  809.                       strcpy(gd->gd_Buffer, (char *)answer->rm_Result2);
  810.  
  811.                   DeleteArgstring((char *)answer->rm_Result2);
  812.                }
  813.             }
  814.  
  815.             DeleteArgstring((char *)ARG0(answer));
  816.  
  817.             DeleteRexxMsg(answer);
  818.  
  819.             return(TRUE);
  820.          }
  821.       }
  822.    }
  823.  
  824.    Permit();
  825.  
  826.    return(FALSE);
  827. }
  828. /*FE*/
  829.  
  830. /* ------------------ allocate memory for a found entry ------------------- */
  831.  
  832. /*FS*/ /*"BOOL alloc_name(struct GlobalData *gd,STRPTR name)"*/
  833. BOOL alloc_name(struct GlobalData *gd,STRPTR name)
  834. {
  835.    struct Node *node;
  836.  
  837.    for(node = gd->gd_FoundList.lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  838.       if(!strcmp(node->ln_Name,name))
  839.          break;
  840.  
  841.    if(node->ln_Succ)
  842.       return(FALSE);
  843.  
  844.    if((node = LibAllocPooled(gd->gd_FoundPool,sizeof(struct Node) + strlen(name) + 1)))
  845.    {
  846.       node->ln_Name = (STRPTR) (node + 1);
  847.       strcpy(node->ln_Name,name);
  848.       insertbyiname(&gd->gd_FoundList,node);
  849.    }
  850.  
  851.    return(TRUE);
  852. }
  853. /*FE*/
  854.  
  855. /* --------------------- select a node out of a list ---------------------- */
  856.  
  857. /*FS*/ /*"struct Node *select_node(struct List *list,struct Screen *screen)"*/
  858. struct Node *select_node(struct List *list,struct Screen *screen)
  859. {
  860.    struct TextAttr txtattr;
  861.    struct TextFont *font;
  862.    struct Node *selnode = NULL;
  863.    UBYTE fontname[32];
  864.  
  865.    /* get the screen font */
  866.    txtattr = *screen->Font;
  867.  
  868.    strncpy(fontname,txtattr.ta_Name,sizeof(fontname));
  869.    txtattr.ta_Name = fontname;
  870.  
  871.    if((font = OpenFont(&txtattr)))
  872.    {
  873.       struct RastPort rp;
  874.       struct NewGadget ng;
  875.       struct Gadget *glist = NULL;
  876.       struct Gadget *gad;
  877.       struct Node *node;
  878.       ULONG max = 100;
  879.       ULONG x;
  880.  
  881.       UWORD width;
  882.       UWORD height;
  883.       UWORD num = 0;
  884.  
  885.       InitRastPort(&rp);
  886.       SetFont(&rp,font);
  887.  
  888.       for(node = list->lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  889.       {
  890.          if((x = TextLength(&rp,node->ln_Name,strlen(node->ln_Name))) > max)
  891.          {
  892.             max = x;
  893.          }
  894.  
  895.          num++;
  896.       }
  897.  
  898.       width  = max + 20 + 16 + 4;
  899.       height = 10 * font->tf_YSize + 4;
  900.  
  901.       ng.ng_LeftEdge   = XDISTANCE;
  902.       ng.ng_TopEdge    = font->tf_YSize + 1 + YDISTANCE;
  903.       ng.ng_Width      = width;
  904.       ng.ng_Height     = height;
  905.       ng.ng_GadgetText = NULL;
  906.       ng.ng_TextAttr   = &txtattr;
  907.       ng.ng_GadgetID   = 1;
  908.       ng.ng_Flags      = 0;
  909.       ng.ng_VisualInfo = GetVisualInfoA(screen,NULL);
  910.       ng.ng_UserData   = NULL;
  911.  
  912.       if((gad = CreateContext(&glist)))
  913.       {
  914.          if((gad = CreateGadget(LISTVIEW_KIND,gad,&ng,
  915.                                 GTLV_Labels       ,list,
  916.                                 GTLV_ShowSelected ,NULL,
  917.                                 GTLV_Selected     ,0,
  918.                                 TAG_DONE)))
  919.  
  920.  
  921.          {
  922.             struct Window *win;
  923.  
  924.             width  += 2 * XDISTANCE;
  925.             height += 2 * YDISTANCE + font->tf_YSize + 1;
  926.  
  927.             if((win = OpenWindowTags(NULL,
  928.                                      WA_Title        ,prgname,
  929.                                      WA_Left         ,(screen->Width  - width ) >> 1,
  930.                                      WA_Top          ,(screen->Height - height) >> 1,
  931.                                      WA_Width        ,width,
  932.                                      WA_Height       ,height,
  933.                                      WA_AutoAdjust   ,TRUE,
  934.                                      WA_Gadgets      ,glist,
  935.                                      WA_IDCMP        ,IDCMP_RAWKEY | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | LISTVIEWIDCMP ,
  936.                                      WA_Flags        ,WFLG_CLOSEGADGET | WFLG_DEPTHGADGET | WFLG_DRAGBAR | WFLG_NOCAREREFRESH | WFLG_ACTIVATE,
  937.                                      WA_CustomScreen ,screen,
  938.                                      TAG_DONE)))
  939.             {
  940.                struct IntuiMessage *msg;
  941.                ULONG startsec,startmic,endsec,endmic;
  942.                BOOL running  = TRUE;
  943.                BOOL clicked  = FALSE;
  944.                WORD selected = -1;
  945.                WORD actual   = 0;
  946.  
  947.                GT_RefreshWindow(win,NULL);
  948.  
  949.                while(running)
  950.                {
  951.                   WaitPort(win->UserPort);
  952.                   while((msg = GT_GetIMsg(win->UserPort)))
  953.                   {
  954.                      switch(msg->Class)
  955.                      {
  956.                      case IDCMP_GADGETUP:
  957.                         if(!clicked)
  958.                         {
  959.                            CurrentTime(&startsec,&startmic);
  960.                            clicked = TRUE;
  961.                         } else if(msg->Code != actual)
  962.                         {
  963.                            clicked = FALSE;
  964.                         } else
  965.                         {
  966.                            CurrentTime(&endsec,&endmic);
  967.                            if(DoubleClick(startsec,startmic,endsec,endmic))
  968.                            {
  969.                               selected = actual;
  970.                               running = FALSE;
  971.                            }
  972.                            clicked = FALSE;
  973.                         }
  974.                         actual = msg->Code;
  975.                         break;
  976.                      case IDCMP_RAWKEY:
  977.                         switch(msg->Code)
  978.                         {
  979.                         case CURSORUP:
  980.                            if(actual > 0)
  981.                            {
  982.                               if(msg->Qualifier & 0x03)
  983.                               {
  984.                                  actual -= 9;
  985.                                  actual  = MAX(actual,0);
  986.                               } else
  987.                                  actual--;
  988.                               GT_SetGadgetAttrs(gad,win,NULL,
  989.                                                 GTLV_Selected    ,actual,
  990.                                                 GTLV_MakeVisible ,actual,
  991.                                                 (GadToolsBase->lib_Version < 39 ) ? GTLV_Top : TAG_IGNORE ,actual,
  992.                                                 TAG_DONE);
  993.                            }
  994.                            break;
  995.                         case  CURSORDOWN:
  996.                            if(actual < num - 1)
  997.                            {
  998.                               if(msg->Qualifier & 0x03)
  999.                               {
  1000.                                  actual += 9;
  1001.                                  actual  = MIN(actual,num-1);
  1002.                               } else
  1003.                                  actual++;
  1004.                               GT_SetGadgetAttrs(gad,win,NULL,
  1005.                                                 GTLV_Selected    ,actual,
  1006.                                                 GTLV_MakeVisible ,actual,
  1007.                                                 (GadToolsBase->lib_Version < 39 ) ? GTLV_Top : TAG_IGNORE  ,actual,
  1008.                                                 TAG_DONE);
  1009.                            }
  1010.                            break;
  1011.                         }
  1012.                         break;
  1013.                      case IDCMP_VANILLAKEY:
  1014.                         switch(msg->Code)
  1015.                         {
  1016.                         case 13:    /* return */
  1017.                            selected = actual;
  1018.                         case 3:     /* ctrl-c */
  1019.                         case 27:    /* esc */
  1020.                            running = FALSE;
  1021.                            break;
  1022.                         }
  1023.                         break;
  1024.                      case IDCMP_CLOSEWINDOW:
  1025.                         running = FALSE;
  1026.                         break;
  1027.                      }
  1028.                      GT_ReplyIMsg(msg);
  1029.                   }
  1030.                }
  1031.  
  1032.                if(selected > -1)
  1033.                {
  1034.                   for(selnode = list->lh_Head ;
  1035.                       selnode->ln_Succ && selected > 0 ;
  1036.                       selnode = selnode->ln_Succ)
  1037.                   {
  1038.                      selected--;
  1039.                   }
  1040.  
  1041.                   if(!selnode->ln_Succ)
  1042.                      selnode = NULL;
  1043.  
  1044.                }
  1045.  
  1046.                DB(("close window : %lx\n",win));
  1047.  
  1048.                CloseWindow(win);
  1049.             }
  1050.          }
  1051.          FreeGadgets(glist);
  1052.       }
  1053.       CloseFont(font);
  1054.    }
  1055.    return(selnode);
  1056. }
  1057. /*FE*/
  1058.  
  1059. /* -------------------------- support functions --------------------------- */
  1060.  
  1061. /*FS*/ /*"void parse_typestring(STRPTR typestr,ULONG *typearray)"*/
  1062. void parse_typestring(STRPTR typestr,ULONG *typearray)
  1063. {
  1064.    STRPTR end = typestr;
  1065.    STRPTR ptr = typestr;
  1066.    ULONG types = 0;
  1067.    ULONG i;
  1068.  
  1069.    /* convert separator to EOS */
  1070.    while(*end != EOS)
  1071.    {
  1072.       if(*end == '|')
  1073.          *end = EOS;
  1074.       end++;
  1075.    }
  1076.  
  1077.    while(ptr < end)
  1078.    {
  1079.       for(i = 0 ; i < XREFT_MAXTYPES ; i++)
  1080.          if(!Stricmp(ptr,xreftype_names[i]))
  1081.          {
  1082.             DB(("type : %s found -> %ld\n",ptr,i));
  1083.             typearray[types] = i;
  1084.             types++;
  1085.             break;
  1086.          }
  1087.  
  1088.       ptr += strlen(ptr) + 1;
  1089.    }
  1090.  
  1091.    DB(("types : %ld\n",types));
  1092.  
  1093.    typearray[types] = ~0;
  1094. }
  1095. /*FE*/
  1096.  
  1097.